package com.kum.websocket.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kum.websocket.pojo.coordinate;
import com.kum.websocket.pojo.fightInfo;
import com.kum.websocket.pojo.infoMsg;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

@Slf4j
@Component
@ServerEndpoint(value = "/test")
public class MySocket {
    private static int userCount = 0;
    private static ConcurrentHashMap<String, Session>
            webSocketMap = new ConcurrentHashMap<>();
    private static ConcurrentHashMap<String, fightInfo>
            UserGameInfoMap = new ConcurrentHashMap<>();
    private static List<String>
            onlineList = new CopyOnWriteArrayList<>();
    private static List<int[][]>
            GameRoomList = new CopyOnWriteArrayList<>();

    private String UserName = "";
    private Session session;

    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
    }

    @OnClose
    public void onClose() throws IOException {
        log.info("{}退出游戏", UserName);
        webSocketMap.remove(UserName);
        onlineList.remove(UserName);
        userCount--;
        /*
         * 检测是不是还在游戏中.是则通知对方游戏已结束!
         */
        if (UserGameInfoMap.get(UserName) != null) {
            fightInfo f = UserGameInfoMap.get(UserName);
            Session target = webSocketMap.get(f.getTarget());
            sendMessage(target, new infoMsg(10, "由于你过于强大,对方逃跑了!").toJson());
            GameRoomList.remove(Integer.valueOf(f.getRoomId()) - 1);
            UserGameInfoMap.remove(UserName);

        }
        sendUserAll(UserName, 11); // 通知全体在线用户,该用户已下线.

    }

    @OnMessage
    public void onMessage(String msg) throws IOException {
        JSONObject parse = (JSONObject) JSON.parse(msg);
        String type = parse.get("type").toString();
        String name = null;
        String target = null;
        switch (type) {
            case "UserList":
                getUserList();
                break;

            case "create":
                name = parse.get("name").toString();
                UserCreate(name);
                break;

            case "challenge":
                name = parse.get("name").toString();
                sendChallenge(name);
                break;

            case "RequestGame":
                String Judge = parse.get("agree").toString();
                target = parse.get("target").toString();
                name = parse.get("name").toString();
                GameCreate(Judge, name, target);
                break;
            case "PlayChess":
                name = parse.get("name").toString();
                target = parse.get("target").toString();
                String color = parse.get("color").toString();
                String x = parse.get("x").toString();
                String y = parse.get("y").toString();
                PlayChess(name, target, color, x, y);

        }


    }

    public void UserCreate(String name) throws IOException {

        if (webSocketMap.containsKey(name)) {
            sendMessage(this.session, new infoMsg(2, "用户名重复!").toJson());
        } else {
            this.UserName = name;
            log.info("{}创建用户成功", name);
              /*
                通知所有用户,新增一名用户
              */
            sendUserAll(name, 4);
            webSocketMap.put(name, this.session);
            sendMessage(this.session, new infoMsg(1, "创建用户成功!!").toJson());
            userCount++;
            if (onlineList.size() != 0) {
                getUserList(); //给当前用户发送未进行游戏用户的列表
            }
            onlineList.add(name);
        }

    }

    public void GameCreate(String Judge, String name, String target) throws IOException {
        //拒绝对局
        Session targets = webSocketMap.get(target);
        if (Judge.equals("false")) {
            sendMessage(targets, new infoMsg(6, "对方拒绝了你的挑战!").toJson());
            return;
        }
        //创建房间
        GameRoomList.add(new int[16][16]);
        String RoomId = GameRoomList.size() + "";

        //给双方发送游戏房间Id
        sendMessage(this.session, new infoMsg(7, RoomId).toJson());
        sendMessage(targets, new infoMsg(7, RoomId).toJson());

        /*
           取随机数,选择一名用户为先手(黑棋,后者为白).
           如果随机数为奇数,则通知当前session为先手(通知 "1"),反之为后手.
        */
        int a = 2, b = 2;
        if (((int) ((Math.random() * 10)) & 1) == 1) a = 1;
        else b = 1;
        sendMessage(this.session, new infoMsg(8, a + "").toJson());
        sendMessage(targets, new infoMsg(8, b + "").toJson());

        //将双方信息记录下来(对手信息与所执什么颜色的棋子)
        UserGameInfoMap.put(name, new fightInfo(name, target, a + "", RoomId));
        UserGameInfoMap.put(target, new fightInfo(target, name, b + "", RoomId));

        //从正在游戏中删除


        //向所有玩家更新名单


    }

    public void sendChallenge(String name) throws IOException {
        Session temp = webSocketMap.get(name);
        if (temp != null) {
            log.info("{} => {}发起挑战", this.UserName, name);
            sendMessage(webSocketMap.get(name), new infoMsg(5, this.UserName).toJson());
        } else {
            sendMessage(this.session, new infoMsg(6, "挑战的用户已下线或不存在!").toJson());

        }


    }

    public void PlayChess(String name, String target, String color, String x, String y) throws IOException {

        fightInfo f = UserGameInfoMap.get(name);
        //对比记录的信息,防止用户作弊. 房间号由服务端决定,无需判断.
        if (new fightInfo(name, target, color, "0").contrast(f)) {
            //更新数组并检查是否达成五子.
            int[][] map = GameRoomList.get(Integer.valueOf(f.getRoomId()) - 1);
            int x1 = Integer.valueOf(x);
            int y1 = Integer.valueOf(y);
            int c1 = Integer.valueOf(color);
            map[x1][y1] = c1;
            sendMessage(webSocketMap.get(target), new infoMsg(8, new coordinate(x, y, color).toJson()).toJson());
            if (GameCheck(x1, y1, map)) {
                String winner = name;
                sendMessage(this.session, new infoMsg(9, winner).toJson());
                sendMessage(webSocketMap.get(target), new infoMsg(9, winner).toJson());

                //删除游戏房间与游戏信息
                GameRoomList.remove(Integer.valueOf(f.getRoomId()) - 1);
                UserGameInfoMap.remove(name);
                UserGameInfoMap.remove(target);

            }
        } else {
            //用户作弊


        }


    }

    public boolean GameCheck(int x, int y, int[][] arr) {
        int base = arr[x][y];
        int[][] pn = {{-1, -1}, {-1, 0}, {-1, 1}, {1, -1}, {1, 0}, {1, 1}, {0, -1}, {0, 1}};
        int[] result = new int[8];
        for (int i = 0; i < 8; i++) {
            int count = 0;
            int x1 = x;
            int y1 = y;
            while (true) {
                x1 += pn[i][0];
                y1 += pn[i][1];
                if (x1 < 0 || y1 < 0 || x1 >= arr.length || y1 >= arr.length
                        || arr[x1][y1] != base) {
                    result[i] = count;
                    break;
                } else {
                    count++;
                }
            }
        }
        if (result[0] + result[5] == 4 || result[1] + result[4] == 4 ||
                result[2] + result[3] == 4 || result[6] + result[7] == 4) {
            return true;
        }
        return false;

    }

    public void sendMessage(Session session, String message) throws IOException {
        session.getBasicRemote().sendText(message);
    }

    public void sendUserAll(String name, int opt) throws IOException {
        /*
         * 一共有两种状态,如果name存在,那么为通知有新增用户,反之是通知删除下线用户!
         * */

        for (Map.Entry<String, Session> entry : webSocketMap.entrySet()) {
            sendMessage(entry.getValue(), new infoMsg(opt, name).toJson());
        }
    }

    public void getUserList() throws IOException {
        ArrayList<String> list = new ArrayList<>(onlineList);
        list.remove(UserName);
        if (list.size() != 0) {
            String UserList = JSON.toJSONString(list);
            sendMessage(this.session, new infoMsg(3, UserList).toJson());

        }


    }


}






